package com.fivestar.pmanager.web.auth;

import com.fivestar.pmanager.service.SysRoleOperationRelaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import static com.fivestar.pmanager.core.util.SpringUtil.getBean;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MySecurityMetadataSource implements
        FilterInvocationSecurityMetadataSource
{
    private static final Logger logger = LoggerFactory.getLogger(MySecurityMetadataSource.class);
    private SysRoleOperationRelaService sysRoleOperationRelaService;
    private static Map<String,Collection<ConfigAttribute>> resourceMap = null;
    private PathMatcher pathMatcher = new AntPathMatcher();
    private final String NO_POWER = "NO_POWER";

    public MySecurityMetadataSource(){}
    
    public MySecurityMetadataSource(SysRoleOperationRelaService sysRoleOperationRelaService)
    {
        this.sysRoleOperationRelaService = sysRoleOperationRelaService;
        loadResourceDefine();
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object o)
            throws IllegalArgumentException
    {
        String requestUrl = ((FilterInvocation) o).getRequestUrl();
        logger.debug("requestUrl is:" + requestUrl);
        if(requestUrl.contains("?"))
        {
            requestUrl = requestUrl.substring(0,requestUrl.indexOf("?"));
            logger.debug("修剪后的requestUrl is："+ requestUrl);
        }
        
        if(requestUrl.contains("#"))
        {
            requestUrl = requestUrl.substring(0,requestUrl.indexOf("#"));
            logger.debug("修剪后的requestUrl is："+ requestUrl);
        }
        
        if(resourceMap == null || resourceMap.isEmpty())
        {
            loadResourceDefine();
        }

        for (String url : resourceMap.keySet())
        {
            if(pathMatcher.match(url, requestUrl)) return resourceMap.get(requestUrl);
        }
        
        // 1.按请求url逐个匹配权限 spring_security_core 3.2.6
         List<ConfigAttribute> result = new ArrayList<ConfigAttribute>();
         result.add(new SecurityConfig(NO_POWER));
         return result;
        // 2.按角色匹配权限 
//        return new ArrayList<ConfigAttribute>();
    }


    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes()
    {
        return null;
    }


    @Override
    public boolean supports(Class<?> aClass)
    {
        return true;
    }


    //加载所有资源与权限的关系
    public void loadResourceDefine()
    {
        logger.info("加载所有资源与权限的关系.");
        resourceMap = new HashMap<>();
        List<Map<String, Object>> roleAndUrls = sysRoleOperationRelaService.findAllRoleAndOperation();
        // 添加公共权限
        List<Map<String, Object>> roleAndUrlsByComm = sysRoleOperationRelaService.findCommRoleAndOperation();
        roleAndUrls.addAll(roleAndUrlsByComm);
        
        for (Map<String, Object> roleAndUrl : roleAndUrls)
        {
            String opnUrl = String.valueOf(roleAndUrl.get("opnUrl"));
            String roleCode = String.valueOf(roleAndUrl.get("code"));
            Collection<ConfigAttribute> configAttributes = resourceMap.get(opnUrl);
            if(configAttributes == null || configAttributes.isEmpty() ) configAttributes = new ArrayList<ConfigAttribute>();
            //以权限名封装为Spring的security Object
            configAttributes.add(new SecurityConfig(roleCode));
            resourceMap.put(opnUrl, configAttributes);
        }
        
        logger.info("加载资源数，size={}", resourceMap.size());
    }


    /**
     * 清理权限资源
     *
     */
    public static void initResourceMap()
    {
        resourceMap = null;
        getBean(MySecurityMetadataSource.class).loadResourceDefine();
    }
}
